package com.gl.saasservice.announcement.service;

import com.gl.common.enums.OSSFileTypeEnum;
import com.gl.common.util.SecurityUtils;
import com.gl.common.vo.ApiData;
import com.gl.framework.security.LoginUser;
import com.gl.framework.web.response.Result;
import com.gl.portal.system.entity.SysDept;
import com.gl.portal.system.repository.SysDeptRepository;
import com.gl.saasservice.announcement.entity.Announcement;
import com.gl.saasservice.announcement.repository.AnnouncementRepository;
import com.gl.saasservice.announcement.vo.AnnouncementVO;
import com.gl.saasservice.oss.config.OssConfig;
import com.gl.saasservice.oss.service.OSSService;
import com.gl.saasservice.entity.Department;
import com.gl.saasservice.repository.DepartmentRepository;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
public class AnnouncementService {
    private static final Logger LOG = LoggerFactory.getLogger(AnnouncementService.class);

    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private OSSService ossService;
    @Autowired
    private AnnouncementRepository announcementRepository;
    @Autowired
    private OssConfig ossConfig;
    @Autowired
    private SysDeptRepository sysDeptRepository;
    @Autowired
    private DepartmentRepository departmentRepository;

    /**
     * OSS 域名
     */
    @Value("${ali.oss.endpoint}")
    private String endpoint;
    /*
     *oss地址
     */
    @Value("${ali.oss.bucket}")
    private String bucket;
    @Autowired
    @Qualifier("stringRedisTemplate")
    private StringRedisTemplate redisTemplate;

    /*
     *公告列表
     */
    public Result pages(String accessToken, Integer pageNumber, Integer pageSize, AnnouncementVO vo) {
        LOG.info("AnnouncementService pages accessToken={},AnnouncementVO={}", accessToken, vo.toString());

        String SQL = " SELECT * FROM saas_announcement a ";

        String count = "SELECT count(1) FROM saas_announcement a ";

        String offsets = " limit ? offset ?";

        StringBuilder where = new StringBuilder("WHERE 1 = 1 \n");
        List<Object> args = new ArrayList<>();

        if (vo != null) {
            if (StringUtils.isNotBlank(vo.getTitle())) {
                where.append(" and a.title like ? ");
                args.add("%" + vo.getTitle() + "%");
            }
            if (StringUtils.isNotBlank(vo.getStartTime())
                    && StringUtils.isNotBlank(vo.getEndTime())) {
                where.append(" and DATE_FORMAT(a.release_time,'%Y-%m-%d') between  DATE_FORMAT( ? , '%Y-%m-%d')  and DATE_FORMAT( ? , '%Y-%m-%d')  ");
                args.add(vo.getStartTime());
                args.add(vo.getEndTime());
            }
        }

        ApiData<AnnouncementVO> apiData = new ApiData<>();
        Long total = jdbcTemplate.queryForObject(count + where, Long.class, args.toArray());
        if (total == 0) {
            return Result.success(apiData);
        }

        // 查询分页数据
        where.append(" ORDER BY ").append(" a.release_time desc ").append(" \n").append(offsets);
        args.add(pageSize);
        args.add(pageNumber * pageSize);
        List<AnnouncementVO> data = jdbcTemplate.query(SQL + where, new BeanPropertyRowMapper<>(AnnouncementVO.class), args.toArray());

        // 查询部门/单位名称
        List<Long> deptIds = data.stream().filter(c -> c.getOrgId() != null && c.getType() == 4).map(AnnouncementVO::getOrgId).distinct().collect(Collectors.toList());
        List<Long> orgIds = data.stream().filter(c -> c.getOrgId() != null && c.getType() != 4).map(AnnouncementVO::getOrgId).distinct().collect(Collectors.toList());
        if (!deptIds.isEmpty()) {
            Map<Long, String> map = sysDeptRepository.findByIdIn(deptIds).stream().collect(Collectors.toMap(SysDept::getId, SysDept::getDeptName));
            if (!map.isEmpty()) {
                data.forEach(c -> {
                    if (c.getType() == 4) {
                        c.setOrgName(map.get(c.getOrgId()));
                    }
                });
            }
        }
        if (!orgIds.isEmpty()) {
            Map<Long, String> map = departmentRepository.findByIdIn(orgIds).stream().collect(Collectors.toMap(Department::getId, Department::getName));
            if (!map.isEmpty()) {
                data.forEach(c -> {
                    if (c.getType() != 4) {
                        c.setOrgName(map.get(c.getOrgId()));
                    }
                });
            }
        }

        apiData.setTotal(total);
        apiData.setData(data);

        return Result.success(apiData);
    }

    /*
     *公告删除
     */
    @Transactional
    public Result delete(String accessToken, Long id) {
        LOG.info("AnnouncementService delete accessToken={},id={}", accessToken, id);

        try {
            Optional<Announcement> announcementOptional = announcementRepository.findById(id);
            if (!announcementOptional.isPresent()) {
                Result.fail("公告不存在");
            }
            Announcement announcement = announcementOptional.get();

            List<String> paths = new ArrayList<>();
            String content = announcement.getContent();
            String homePic = announcement.getHomePic();
            if (StringUtils.isNotBlank(content)) {
                paths = getImgSrc(content);
            }
            if (StringUtils.isNotBlank(homePic)) {
                paths.add(announcement.getHomePic());
            }

            if (!paths.isEmpty()) {
                for (String path : paths) {
                    path = path.replaceAll(endpoint + "/", "");
                    path = path.split("\\?")[0];
                    ossService.deleteObject(bucket, path);
                }
            }
            announcementRepository.deleteById(announcement.getId());

            return Result.success(null);
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            return Result.fail(e.getMessage());
        }
    }

    /**
     * 富文本图片上传
     *
     * @param file
     * @return
     */
    public Map<String, Object> uploadDetailFile(MultipartFile file) {
        try {
            if (file == null) {
                return null;
            }
            Result objectResultBean = ossService.putFile(bucket, file, OSSFileTypeEnum.AD.toString());
            String picUrl = String.valueOf(objectResultBean.getData());
            String ossFilePath = ossService.getOssFilePath(picUrl);
            Map<String, Object> resultMap = new HashMap<>();
            if (StringUtils.isBlank(ossFilePath)) {
                return resultMap;
            }
            resultMap.put("url", ossFilePath);
            return resultMap;
        } catch (Exception e) {
            LOG.error("图片详情上传失败异常" + e.getMessage(), e);
            return null;
        }
    }

    /**
     * 富文本图片删除
     */
    public void deleteDetailFile(String pathStr) {
        try {
            if (StringUtils.isBlank(pathStr)) {
                return;
            }
            String paths[] = pathStr.split(",");
            for (String path : paths) {
                path = path.replaceAll(endpoint + "/", "");
                path = path.split("\\?")[0];
                ossService.deleteObject(bucket, path);
            }
        } catch (Exception e) {
            LOG.error("图片删除异常" + e.getMessage(), e);
        }
    }

    /*
     *图文信息处理
     */
    private List<String> getImgSrc(String htmlStr) {


        List<String> pics = new ArrayList<String>();
        if (htmlStr == null) {
            return pics;
        }

        String img = "";
        Pattern p_image;
        Matcher m_image;


        String regEx_img = "<img.*src\\s*=\\s*(.*?)[^>]*?>";
        p_image = Pattern.compile(regEx_img, Pattern.CASE_INSENSITIVE);
        m_image = p_image.matcher(htmlStr);
        while (m_image.find()) {
            img = img + "," + m_image.group();
            Matcher m = Pattern.compile("src\\s*=\\s*\"?(.*?)(\"|>|\\s+)").matcher(img);
            while (m.find()) {
                pics.add(m.group(1));
            }
        }
        return pics;
    }

    /*
     *公告发布
     */
    public Result save(String accessToken, AnnouncementVO vo, MultipartFile file) {
        LOG.info("AnnouncementService save accessToken={},vo={},file={}", accessToken, vo.toString(), file);

        LoginUser loginUser = SecurityUtils.getLoginUser();

        try {

            if (StringUtils.isBlank(vo.getTitle())) {
                LOG.warn("AnnouncementService save title is NULL");
                return Result.fail("标题为空");
            }
            if (StringUtils.isBlank(vo.getContent())) {
                LOG.warn("AnnouncementService save content is NULL");
                return Result.fail("内容为空");
            }

            Announcement announcement = new Announcement();
            if (vo.getId() == null) {

                if (file == null) {
                    LOG.warn("AnnouncementService save file is NULL");
                    return Result.fail("首页图为空");
                }

                Result objectResultBean = ossService.putFile(bucket, file, OSSFileTypeEnum.AD.toString());
                String picUrl = String.valueOf(objectResultBean.getData());
                String homePic = ossService.getOssFilePath(picUrl);
                AnnouncementVO entity = new AnnouncementVO();
                entity.setOrgId(loginUser.getUser().getDeptId());
                entity.setType(4);//4平台公告
                entity.setReleaseTime(new Date());
                entity.setTitle(vo.getTitle());
                entity.setHomePic(homePic);
                entity.setOperationId(loginUser.getUser().getId().toString());
                entity.setContent(vo.getContent());
                //展示限制：0 APP不展示  1 无限制
                entity.setStatus(1);
                BeanUtils.copyProperties(entity, announcement);
            } else {

                Optional<Announcement> announcementOptional = announcementRepository.findById(vo.getId());
                if (!announcementOptional.isPresent()) {
                    return Result.fail("当前数据已不存在！");
                }
                BeanUtils.copyProperties(announcementOptional.get(), announcement);
                announcement.setTitle(vo.getTitle());

                if (file != null) {
                    String fileKey = announcement.getHomePic().replace(ossConfig.getBucketUrl(), "");
                    ossService.deleteObject(bucket, fileKey);

                    Result objectResultBean = ossService.putFile(bucket, file, OSSFileTypeEnum.AD.toString());
                    String picUrl = String.valueOf(objectResultBean.getData());
                    String homePic = ossService.getOssFilePath(picUrl);
                    announcement.setHomePic(homePic);
                }

                announcement.setContent(vo.getContent());
            }

            Announcement save = announcementRepository.save(announcement);
            return Result.success(null);
        } catch (Exception e) {
            LOG.error("AnnouncementService save Exception = {}", e);
            return Result.fail(e.getMessage());
        }
    }

}
